home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / BROWSE.ASM < prev    next >
Assembly Source File  |  1986-01-02  |  15KB  |  454 lines

  1. ;    BROWSE.ASM -- Full Screen File Pager
  2. ;    ====================================
  3.  
  4. CSEG        Segment
  5.         Assume    CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  6.         Org    0080h
  7. Parameter    Label    Byte
  8.         Org    0100h
  9. Entry:        Jmp Begin
  10.  
  11. ;    All Data
  12. ;    --------
  13.  
  14.         db    'ATTR='
  15. Attribute    db    0        ; Current screen attribute
  16.         db    'SHIFT='
  17. ShiftHoriz    db    8        ; Horizontal shift screen default
  18. DosVersionFail    db    'Requires DOS 2.0 or above$'
  19. NoSpaceFail    db    'Not enough memory$'
  20. FileFail    db    'File Not Found$'
  21. ScreenFail    db    'Unsupported video mode$'
  22. Delimiters    db    9,' ,;=/'    ; Delimiters in parameter
  23. FileHandle    dw    ?        ; Use for saving file handle
  24. WSMode        db    0FFh        ; AND value for non-WordStar mode
  25. LineLength    db    ?        ; Length of line (from BIOS)
  26. NumberLines    db    25,0        ; Number of lines (check EGA BIOS)
  27. ScreenSize    dw    ?        ; Size of screen in bytes
  28. CheckRetrace    db    1        ; Flag zero if EGA or MONO used
  29. Addr6845    dw    ?        ; Could use for retrace check    
  30. ScreenAddr    Label    DWord        ; Address of screen
  31. ScreenOff    dw    0        ; Higher for non-page 0
  32. ScreenSeg    dw    0B800h        ; Set to B000h for Mono Mode 7
  33. ScreenStart    dw    ?        ; Points within buffer 
  34. EndOfFile    dw    ?        ; Points within buffer
  35. FileOffset    dw    -1, -1        ; Address within file of buffer data
  36. HorizOffset    dw    0        ; Horizontal offset for display    
  37. RightMargin    dw    0        ; Right margin for offset display
  38. Dispatch    dw    Home, Up, PgUp, Dummy, Left
  39.         dw    Dummy, Right, Dummy, End, Down, PgDn
  40.  
  41. ;    Check DOS Version for 2.0 or above
  42. ;    ----------------------------------
  43.  
  44. Begin:        Cld            ; All string directions forward
  45.         Mov    AH,30h
  46.         Int    21h        ; Get DOS Version Number
  47.         Cmp    AL,2        ; Check for 2.0 or later
  48.         Jae    DOSVerOK
  49.         Mov    DX,Offset DOSVersionFail
  50. ErrorExit:    Mov    AH,9        ; Write error message
  51.         Int    21h
  52.         Int    20h
  53.  
  54. ;    Parse Command Line to get File Name and WordStar flag
  55. ;    -----------------------------------------------------
  56.  
  57. DOSVerOK:    Mov    SI,1 + Offset Parameter    ; Points to parameter
  58. NameSearch:    Lodsb                ; Get byte
  59.         Cmp    AL,13            ; Check if carriage return
  60.         Jz    NoFileFound        ; If so, no file name
  61.         Mov    DI,Offset Delimiters    ; String of delimiters
  62.         Mov    CX,5            ; Number of delimiters (no /)
  63.         Repne    Scasb            ; See if a match
  64.         Je    NameSearch        ; If a delimiter, keep looking
  65.         Mov    DX,SI            ; Otherwise found file name
  66.         Dec    DX            ; Points to beginning of it
  67. EndSearch:    Lodsb                ; Get next byte
  68.         Cmp    AL,13            ; See if carriage return
  69.         Je    GotFileEnd        ; If so, we're all done
  70.         Mov    DI,Offset Delimiters    ; String of delimiters
  71.         Mov    CX,6            ; Number (including /)
  72.         Repne    Scasb            ; See if a match
  73.         Jne    EndSearch        ; If not, still in file name
  74.         Mov    Byte Ptr [SI - 1],0    ; If so, mark end of file name
  75.         Jcxz    GotFlag            ; If slash, check for W
  76.         Jmp    EndSearch        ; Or continue flag search
  77. GotFlag:    Lodsb                ; Get byte after / flag
  78.         Or    AL,20h            ; Uncapitalize
  79.         Cmp    AL,'w'            ; See if w for WordStar mode
  80.         Jnz    GotFileEnd        ; If not, just ignore it
  81.         Mov    [WSMode],7Fh        ; AND value for WordStar
  82.  
  83. ;    Open the File
  84. ;    -------------
  85.  
  86. GotFileEnd:    Mov    Byte Ptr [SI - 1],0    ; Mark end of file name
  87.                         ; DX still points to name
  88.         Mov    AX,3D00h        ; Open file for reading
  89.         Int    21h            ;   by calling DOS
  90.         Jnc    GotTheFile        ; If no error, continue    
  91. NoFileFound:    Mov    DX,Offset FileFail    ; Otherwise print a message 
  92.         Jmp    ErrorExit
  93. GotTheFile:    Mov    [FileHandle],AX        ; Save the file handle
  94.  
  95. ;    Get Screen Mode Information from BIOS Data Area
  96. ;    -----------------------------------------------
  97.  
  98.         Push    ES            ; Save register
  99.         Sub    AX,AX
  100.         Mov    ES,AX            ; Set ES to 0 (BIOS Data)
  101.         Mov    AL,ES:[0449h]        ; Current Video Mode
  102.         Cmp    AL,3            ; Check if Color Alpha
  103.         Jbe    DisplayOK        ; Continue if so
  104.         Cmp    AL,7            ; Check if monochrome display
  105.         Je    Monochrome        ; If so, branch
  106.         Mov    DX,Offset ScreenFail    ; We can't handle graphics
  107.         Jmp    ErrorExit        ; So print an error message
  108. Monochrome:    Mov    [ScreenSeg],0B000h    ; Use Monochrome Segment
  109.         Mov    [CheckRetrace],0    ; Don't have to check retrace
  110. DisplayOK:    Mov    AL,ES:[044Ah]        ; Number of Columns
  111.         Mov    [LineLength],AL        ; Save it
  112.         Mov    AX,ES:[044Eh]        ; Offset into screen buffer
  113.         Mov    [ScreenOff],AX        ; Save it         
  114.         Mov    AX,ES:[0463h]        ; Address of 6845 Regsiter
  115.         Mov    [Addr6845],AX        ; Save it
  116.         Push    ES
  117.         Sub    DL,DL            ; Set Rows to zero first
  118.         Sub    BH,BH
  119.         Mov    AX,1130h        ; EGA BIOS: Get Information
  120.         Int    10h
  121.         Pop    ES
  122.         Or    DL,DL            ; Check if DL is still zero
  123.         Jz    NoEGA            ; If so, skip rest of stuff
  124.         Inc    DL
  125.         Mov    [NumberLines],DL    ; Save Number of Lines
  126.         Test    Byte Ptr ES:[0487h],4    ; Check if must check retrace
  127.         Jnz    NoEGA
  128.         Mov    [CheckRetrace],0    ; EGA says we don't have to
  129. NoEGA:        Mov    BH,ES:[0462h]        ; Get Current Page (use later)
  130.         Pop    ES
  131.         Mov    AL,[LineLength]        ; Length of each line
  132.         Mul    [NumberLines]        ; Total chars on screen
  133.         Add    AX,AX            ; Double for attributes
  134.         Mov    [ScreenSize],AX        ; And Save it
  135.  
  136. ;    See if enough memory is left
  137. ;    ----------------------------
  138.  
  139.         Add    AX,Offset ScreenHold    ; Add ScreenSize to code end
  140.         Add    AX,256            ; Add a little stack room
  141.         Cmp    AX,SP            ; Check against stack pointer
  142.         Jbe    GotEnufMemory        ; Continue if OK
  143.         Mov    DX,Offset NoSpaceFail    ; Otherwise end program
  144.         Jmp    ErrorExit        ;    with error messae
  145.         
  146. ;    Get Current Screen Attribute
  147. ;    ---------------------------- 
  148.  
  149. GotEnufMemory:    Cmp    [Attribute],0        ; Check if attribute pre-set
  150.         Jnz    GotAttribute        ; If so, move on
  151.         Mov    DL,' '            ; Write out a byte
  152.         Mov    AH,2            ;   using DOS
  153.         Int    21h
  154.         Mov    AL,8            ; Now backspace
  155.         Mov    AH,14            ;   using BIOS call
  156.         Int    10h
  157.         Mov    AH,8            ; Read character & attribute
  158.         Int    10h            ;   using BIOS call (BH = pg)
  159.         Mov    [Attribute],AH        ; And save attribute
  160.  
  161. ;    Save Current Screen
  162. ;    -------------------
  163.  
  164. GotAttribute:    Mov    DX,Offset Terminate    ; Set Ctrl-Break exit
  165.         Mov    AX,2523h        ;   to terminate that way
  166.         Int    21h
  167.         Mov    DI,Offset ScreenHold    ; Destination of screen
  168.         Mov    CX,[ScreenSize]        ; Size of screen
  169.         Push    DS            ; Save Source Segment
  170.         Lds    SI,[ScreenAddr]        ; Get screen address
  171.         Rep    Movsb            ; Move in the bytes
  172.         Pop    DS            ; Restore Source Segment
  173.  
  174. ;    Get Keyboard Key and Decide on Action
  175. ;    -------------------------------------
  176.  
  177.         Call    Home            ; Read file in
  178.         Mov    [ScreenStart],SI    ; Set buffer address
  179. KeyLoop:    Call    UpDateScreen        ; Write file to screen
  180. GetKey:        Mov    AH,8            ; Get key
  181.         Int    21h            ;   by calling DOS
  182.         Cmp    AL,27            ; Check if ESC
  183.         Je    Terminate        ; If so, terminate 
  184.         Cmp    AL,0            ; Check if extended
  185.         Jnz    GetKey            ; If not, try again
  186.         Mov    AH,8            ; Get extended code
  187.         Int    21h            ;   by calling DOS
  188.         Sub    AL,71            ; Subtract Home key value
  189.         Jb    GetKey            ; If below that, not valid
  190.         Cmp    AL,(81 - 71)        ; Check if above PgDn
  191.         Ja    GetKey            ; If so, ignore it
  192.         Sub    AH,AH            ; Zero out top byte
  193.         Add    AX,AX            ; Double for word access
  194.         Mov    BX,AX            ; Offset in dispatch table
  195.         Mov    SI,[ScreenStart]    ; Set current buffer pointer
  196.         Call    [Dispatch + BX]        ; Do the call
  197.         Mov    [ScreenStart],SI    ; Set new buffer pointer
  198.         Jmp    KeyLoop            ; And update the screen
  199.  
  200. ;    Terminate -- Restore screen and close file
  201. ;    ------------------------------------------
  202.  
  203. Terminate:    Mov    SI,Offset ScreenHold    ; Address of Saved Screen
  204.         Les    DI,[ScreenAddr]        ; Address of Display
  205.         Mov    CX,[ScreenSize]        ; Number of characters
  206.         Rep    Movsb            ; Move them back 
  207.         Mov    BX,[FileHandle]        ; Get File Handle
  208.         Mov    AH,3Eh            ; Close File
  209.         Int    21h
  210.         Int    20h            ; Terminate
  211.  
  212. ;    Cursor Key Routines -- Home Key
  213. ;    -------------------------------
  214.  
  215. Home:        Sub    BX,BX            ; For zeroing out values
  216.         Mov    AX,[FileOffset]        ; Check if read in file
  217.         Or    AX,[FileOffset + 2]
  218.         Mov    [FileOffset],BX        ; Zero out file address
  219.         Mov    [FileOffset + 2],BX
  220.         Mov    [HorizOffset],BX    ; Zero out horizontal offset    
  221.         Mov    SI,Offset Buffer    ; Reset buffer pointer    
  222.         Jz    Dummy            ; Skip file read if in already
  223.         Mov    DX,Offset Buffer    ; Area to read file in
  224.         Mov    CX,32768        ; Number of bytes to read
  225.         Call    FileRead        ; Read in file
  226. Dummy:        Ret
  227.  
  228. ;    Up and PgUp Keys
  229. ;    ----------------
  230.  
  231. Up:        Call    GetPrevChar        ; Get previous char in buffer
  232.         Jc    UpDone            ; If none available, finish
  233. UpLoop:        Call    GetPrevChar        ; Get previous char again
  234.         Jc    UpDone            ; if none, we're done
  235.         Cmp    AL,10            ; Check if line feed
  236.         Jnz    UpLoop            ; If not, try again 
  237.         Call    GetNextChar        ; Get char after line feed
  238. UpDone:        Ret
  239.  
  240. PgUp:        Mov    CX,Word Ptr [NumberLines]    ; Number of lines
  241. PgUpLoop:    Call    Up            ; Do UP that many times
  242.         Loop    PgUpLoop
  243.         Ret
  244.  
  245. ;    Left and Right Keys
  246. ;    -------------------
  247.  
  248. Left:        Mov    [HorizOffset],0        ; Reset Horizontal Offset
  249.         Ret
  250.  
  251. Right:        Mov    AL,[ShiftHoriz]        ; Get places to shift
  252.         Sub    AH,AH
  253.         Add    [HorizOffset],AX    ; Move that many right
  254.         Ret
  255.  
  256. ;    End, Down, and PgDn Keys
  257. ;    ------------------------
  258.  
  259. End:        Mov    BX,SI            ; Save buffer pointer
  260.         Call    PgDn            ; Go page down
  261.         Cmp    BX,SI            ; Check if we did so
  262.         Jnz    End            ; If so, do it again
  263.         Ret
  264.  
  265. Down:        Call    GetNextChar        ; Get next character
  266.         Jc    NoMoreDown        ; If no more, we're done
  267. DownLoop:    Call    GetNextChar        ; Get one again
  268.         Jc    UpLoop            ; If no more, find prev LF
  269.         Cmp    AL,10            ; See if line feed
  270.         Jnz    DownLoop        ; If not, continue
  271. NoMoreDown:    Ret
  272.  
  273. PgDn:        Mov    CX,Word Ptr [NumberLines]    ; Number of lines
  274. PgDnLoop:    Call    Down            ; Do DOWN that many times
  275.         Loop    PgDnLoop
  276.         Ret
  277.  
  278. ;    Update Screen
  279. ;    -------------
  280.  
  281. UpdateScreen:    Push    ES
  282.         Mov    SI,[ScreenStart]    ; Address of data in buffer
  283.         Les    DI,[ScreenAddr]        ; Address of display
  284.         Mov    CX,ScreenSize        ; Number of bytes in screen
  285.         Shr    CX,1            ; Half for number of chars
  286.         Mov    AL,' '            ; Will blank screen
  287.         Mov    AH,[Attribute]        ; With screen attribute
  288.         Rep    Stosw            ; Blank it
  289.         Mov    AL,[LineLength]        ; Length of display line
  290.         Sub    AH,AH
  291.         Add    AX,[HorizOffset]    ; Add Horizontal Offset
  292.         Mov    [RightMargin],AX    ; That's right display margin
  293.         Sub    DL,DL            ; Line Number
  294. LineLoop:    Sub    BX,BX            ; Column Number
  295.         Mov    AL,[LineLength]        ; Use Line Length
  296.         Mul    DL            ;   and Line Number
  297.         Add    AX,AX            ;     to recalculate
  298.         Mov    DI,AX            ;       display destination
  299.         Add    DI,[ScreenOff]        ; Add beginning address    
  300. CharLoop:    Call    GetNextChar        ; Get next character
  301.         Jc    EndOfScreen        ; If no more, we're done
  302.         And    AL,[WSMode]        ; Will be 7Fh for WordStar
  303.         Cmp    AL,13            ; Check for carriage return
  304.         Je    CharLoop        ; Do nothing if so
  305.         Cmp    AL,10            ; Check for line feed
  306.         Je    LineFeed        ; Do routine if so
  307.         Cmp    AL,9            ; Check for tab
  308.         Je    Tab            ; Do routine if so
  309.         Mov    CX,1            ; Just 1 char to display
  310. PrintChar:    Cmp    BX,[HorizOffset]    ; See if we can print it
  311.         Jb    NoPrint        
  312.         Cmp    BX,[RightMargin]    ; See if within margin
  313.         Jae    NoPrint
  314.         Mov    AH,[Attribute]        ; Attribute for display
  315.         Cmp    [CheckRetrace],0    ; See if must stop snow
  316.         Jz    WriteIt            ; If not, skip retrace wait
  317.         Push    BX
  318.         Push    DX
  319.         Mov    BX,AX            ; Save character and attribute
  320.         Mov    DX,[Addr6845]        ; Set up I/O address
  321.         Add    DX,6 
  322. RetraceWait1:    In    AL,DX            ; Check until
  323.         Shr    AL,1            ;   vertical retrace
  324.         Jc    RetraceWait1        ;     ends
  325.         Cli                ; Clear interrupts
  326. RetraceWait2:    In    AL,DX            ; Check until
  327.         Shr    AL,1            ;   vertical retrace
  328.         Jnc    RetraceWait2        ;     begins
  329.         Mov    AX,BX            ; Get back character & attr
  330.         Stosw                ; Write to display
  331.         Sti                ; Enable interrupts again
  332.         Pop    DX
  333.         Pop    BX
  334.         Jmp    Short NoPrint        ; Skip around "no snow" write
  335. WriteIt:    Stosw                ; Write without retrace wait
  336. NoPrint:    Inc    BX            ; Bump up line counter
  337.         Loop    PrintChar        ; Do it CX times
  338.         Jmp    CharLoop        ; Then go back to top
  339. Tab:        Mov    AX,BX            ; Current column number
  340.         And    AX,07h            ; Take lower three bits
  341.         Mov    CX,8
  342.         Sub    CX,AX            ; Subtract from 8
  343.         Mov    AL,' '            ; Will print CX blanks
  344.         Jmp    PrintChar
  345. LineFeed:    Inc    DL            ; Next line
  346.         Cmp    DL,[NumberLines]    ; See if down at bottom
  347.         Jb    LineLoop        ; If not, continue
  348. EndOfScreen:    Pop    ES            ; All done -- leave
  349.         Ret
  350.  
  351. ;    Get Next Character from buffer
  352. ;    ------------------------------
  353. ;        (Input is SI pointing to buffer, Returns AL, CY if no more)
  354.  
  355. GetNextChar:    Cmp    SI,[EndOfFile]        ; See if at end of file
  356.         Jae    NoMoreNext        ; If so, no more chars
  357.         Cmp    SI,Offset BufferEnd    ; See if at end of buffer
  358.         Jb    CanGetNext        ; If not, just get character
  359.         Push    CX            ; Otherwise save registers
  360.         Push    DX
  361.         Push    DI
  362.         Push    ES
  363.         Push    DS            ; Set ES to DS
  364.         Pop    ES            ;   (could be different)
  365.         Mov    SI,Offset BufferMid    ; Move 2nd buffer half
  366.         Mov    DI,Offset Buffer    ;   to 1st buffer half    
  367.         Mov    CX,16384       
  368.         Sub    [ScreenStart],CX    ; New buffer pointer
  369.         Rep    Movsb            ; Move them
  370.         Mov    SI,DI            ; SI also buffer pointer
  371.         Add    [FileOffset],32768     ; Adjust file addr to read
  372.         Adc    [FileOffset + 2],0 
  373.         Mov    DX,Offset BufferMid    ; Place to read file
  374.         Mov    CX,16384        ; Number of bytes
  375.         Call    FileRead        ; Read the file
  376.         Sub    [FileOffset],16384    ; Now adjust so reflects
  377.         Sbb    [FileOffset + 2],0    ;   1st half of buffer
  378.         Pop    ES            ; Get back registers
  379.         Pop    DI
  380.         Pop    DX
  381.         Pop    CX
  382.         Jmp    GetNextChar        ; And try again to get char
  383. CanGetNext:    Lodsb                ; Get the character
  384. NoMoreNext:    Cmc                ; So CY set if no more
  385.         Ret                
  386.  
  387. ;    Get Previous Character from buffer
  388. ;    ----------------------------------
  389.  
  390. GetPrevChar:    Cmp    SI,Offset Buffer    ; See if at top of buffer
  391.         Ja    CanGetPrev        ; If not, just get character
  392.         Mov    AX,[FileOffset]        ; See if at top of file
  393.         Or    AX,[FileOffset + 2]
  394.         Jz    AtTopAlready        ; If so, can't get anymore
  395.         Push    CX            ; Save some registers
  396.         Push    DX
  397.         Mov    SI,Offset Buffer    ; Move 1st half of buffer
  398.         Mov    DI,Offset BufferMid    ;   to 2nd half of buffer
  399.         Mov    CX,16384
  400.         Add    [ScreenStart],CX    ; New buffer pointer
  401.         Rep    Movsb            ; Do the move
  402.         Sub    [FileOffset],16384    ; Adjust file addr for read
  403.         Sbb    [FileOffset + 2],0
  404.         Mov    DX,Offset Buffer    ; Area to read file into
  405.         Mov    CX,16384        ; Number of bytes
  406.         Call    FileRead        ; Read the file
  407.         Pop    DX            ; Get back registers
  408.         Pop    CX
  409.         Jmp    Short CanGetPrev    ; Now get character
  410. AtTopAlready:    Stc                ; CY flag set for no more
  411.         Ret
  412. CanGetPrev:    Dec    SI            ; Move pointer back
  413.         Mov    AL,[SI]            ; Get the character
  414.         Clc                ; CY flag reset for success
  415.         Ret
  416.  
  417. ;    Read CX bytes from the file into DX buffer
  418. ;    ------------------------------------------     
  419.  
  420. FileRead:    Push    AX            ; Save some registers
  421.         Push    BX
  422.         Push    CX
  423.         Push    DX
  424.         Mov    [EndOfFile],-1        ; Initialize this
  425.         Mov    DX,[FileOffset]        ; Get file address to read
  426.         Mov    CX,[FileOffset + 2]
  427.         Mov    BX,[FileHandle]        ; Get file Handle
  428.         Sub    AL,AL            ; Do LSEEK from beginning
  429.         Mov    AH,42h            ; LSEEK call
  430.         Int    21h
  431.         Pop    DX            ; Get back destination
  432.         Pop    CX            ; Get back count
  433.         Mov    AH,3Fh            ; Read file function call
  434.         Int    21h
  435.         Jnc    NoReadError        ; If no error, continue
  436.         Sub    AX,AX            ; Otherwise read zero bytes
  437. NoReadError:    Cmp    AX,CX            ; See if 32K has been read
  438.         Je    GotItAll        ; If so, we're home free
  439.         Add    AX,DX            ; Otherwise add to buffer addr
  440.         Mov    [EndOfFile],AX        ; And save as end of file
  441. GotItAll:    Pop    BX
  442.         Pop    AX
  443.         Ret
  444.  
  445. ;    File Buffer and Screen Hold Areas
  446. ;    ---------------------------------
  447.  
  448. Buffer        Label    Byte            ; Area for file reads
  449. BufferMid    equ    Buffer + 16384        ; Halfway through it
  450. BufferEnd    equ    BufferMid + 16384    ; At end of it        
  451. ScreenHold    equ    BufferEnd        ; Area for holding screen
  452. CSEG        EndS                ; End of segment
  453.         End    Entry            ; Denotes entry point
  454.